package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.domain.FamilyMember;
import com.zzyl.nursing.domain.FamilyMemberElder;
import com.zzyl.nursing.dto.ReservationCreateDTO;
import com.zzyl.nursing.service.IElderService;
import com.zzyl.nursing.service.IFamilyMemberElderService;
import com.zzyl.nursing.service.IFamilyMemberService;
import com.zzyl.nursing.vo.ReservationTimeCountVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.ReservationMapper;
import com.zzyl.nursing.domain.Reservation;
import com.zzyl.nursing.service.IReservationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.Arrays;

/**
 * 预约信息Service业务层处理
 *
 * @author zhangyan
 * @date 2025-06-06
 */
@Service
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements IReservationService {
    @Autowired
    private ReservationMapper reservationMapper;

    @Autowired
    private IFamilyMemberElderService familyMemberElderService;

    @Autowired
    private IElderService elderService;

    @Autowired
    private IFamilyMemberService familyMemberService;

    @Autowired
    private IReservationService reservationService;

    /**
     * 查询预约信息
     *
     * @param id 预约信息主键
     * @return 预约信息
     */
    @Override
    public Reservation selectReservationById(Long id) {
        return getById(id);
    }

    /**
     * 查询预约信息列表
     *
     * @param reservation 预约信息
     * @return 预约信息
     */
    @Override
    public List<Reservation> selectReservationList(Reservation reservation) {
        return reservationMapper.selectReservationList(reservation);
    }

    /**
     * 新增预约信息
     *
     * @param reservation 预约信息
     * @return 结果
     */
    @Override
    public int insertReservation(Reservation reservation) {
        return save(reservation) ? 1 : 0;
    }

    /**
     * 修改预约信息
     *
     * @param reservation 预约信息
     * @return 结果
     */
    @Override
    public int updateReservation(Reservation reservation) {
        return updateById(reservation) ? 1 : 0;
    }

    /**
     * 批量删除预约信息
     *
     * @param ids 需要删除的预约信息主键
     * @return 结果
     */
    @Override
    public int deleteReservationByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除预约信息信息
     *
     * @param id 预约信息主键
     * @return 结果
     */
    @Override
    public int deleteReservationById(Long id) {
        return removeById(id) ? 1 : 0;
    }



    @Override
    public Long cancelled(Long userId) {
        // 校验用户 ID
        if (ObjUtil.isEmpty(userId)) {
            throw new BaseException("用户 ID 不存在");
        }

        // 查询家庭成员信息
        FamilyMember familyMember = familyMemberService.selectFamilyMemberById(userId);
        if (familyMember == null) {
            throw new BaseException("用户不存在");
        }

        String phone = familyMember.getPhone();
        // 校验手机号
        if (StrUtil.isEmpty(phone) || phone.length() != 11) {
            throw new BaseException("用户手机号异常");
        }
        if (!ReUtil.isMatch("^1\\d{10}$", phone)) {
            throw new BaseException("手机号格式非法");
        }

        LocalDateTime localDateTime = LocalDate.now().atStartOfDay();

        // 查询被取消的预约数量
        return reservationService.count(new LambdaQueryWrapper<Reservation>()
                .eq(Reservation::getMobile, phone)
                .eq(Reservation::getStatus, 2)
                .gt(Reservation::getTime,localDateTime));
    }

    @Override
    public List<ReservationTimeCountVO> countList(LocalDateTime startTime) {
        if (ObjectUtil.isEmpty(startTime)) {
            throw new BaseException("参数异常");
        }
        LocalDateTime endTime = startTime.plusDays(1);
        return reservationMapper.selectTimeCount(startTime, endTime);
    }



    @Override
    public void add(ReservationCreateDTO dto) {
        // 判空校验，防止前端传入空对象
        if (ObjUtil.isEmpty(dto)) {
            throw new BaseException("参数异常");
        }
        // 提取参数
        String mobile = dto.getMobile();         // 手机号
        String visitor = dto.getVisitor();       // 参观者姓名（或绑定老人姓名）
        Integer type = dto.getType();            // 预约类型（如是否需要校验）

        Long userId = UserThreadLocal.getUserId(); // 获取当前用户ID（用于记录创建人）
        Reservation reservation = BeanUtil.toBean(dto, Reservation.class); // DTO 转为实体

        // 根据预约类型执行不同逻辑
        if (type == 1) {
            // 需要校验家庭成员和老人关系
            calibration(mobile, visitor);
        }

        reservation.setStatus(0);

        // 校验：同一手机号+同一时间段+待处理状态下不能重复预约
        LocalDateTime time = dto.getTime();
        LambdaQueryWrapper<Reservation> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Reservation::getMobile, mobile);
        lambdaQueryWrapper.eq(Reservation::getTime, time);
        lambdaQueryWrapper.in(Reservation::getStatus, 0, 1);
        Reservation reservation1 = reservationMapper.selectOne(lambdaQueryWrapper);
        if (ObjUtil.isNotNull(reservation1)) {
            throw new BaseException("该手机号在该时间段已经预约");
        }
        // 设置创建人ID
        reservation.setCreateBy(String.valueOf(userId));

        // 插入数据库
        reservationMapper.insert(reservation);
    }


    /**
     * 校验手机号是否与老人正确绑定关系
     * @param mobile 手机号
     * @param visitor 老人姓名（用于核对）
     */
    private void calibration(String mobile, String visitor) {
        // 查询手机号对应的家庭成员
        FamilyMember familyMember = familyMemberService.getOne(
                new LambdaQueryWrapper<FamilyMember>().eq(FamilyMember::getPhone, mobile)
        );
        if (familyMember == null || familyMember.getId() == null) {
            throw new BaseException("未找到对应的家庭成员信息");
        }

        // 查询该家庭成员绑定的老人
        List<FamilyMemberElder> list = familyMemberElderService.list(
                new LambdaQueryWrapper<FamilyMemberElder>().eq(FamilyMemberElder::getMemberId, familyMember.getId())
        );
        if (list == null) {
            throw new BaseException("该家庭成员未绑定老人，请先完成绑定");
        }
    }


    @Override
    public List<Reservation> pageList(Integer status) {

        Long userId = UserThreadLocal.getUserId();
        LambdaQueryWrapper<Reservation> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjUtil.isNotNull(status)){
            queryWrapper.eq(Reservation::getStatus,status);
        }
        queryWrapper.eq(Reservation::getCreateBy,userId);
        queryWrapper.gt(Reservation::getTime,LocalDateTime.now());
        queryWrapper.orderByDesc(Reservation::getTime);
        return list(queryWrapper);
    }

    @Override
    public void edit(Long id) {
        if (ObjUtil.isNull(id) || id < 0){
            throw new BaseException("参数异常");
        }

        Reservation oldReservation = getById(id);
        if (ObjUtil.isNull(oldReservation)){
            throw new BaseException("预约不存在");
        }
        if (oldReservation.getStatus().equals(2)){
            throw new BaseException("已取消");
        }
        if (oldReservation.getStatus().equals(1)){
            throw new BaseException("已完成");
        }
        if (oldReservation.getStatus().equals(3)){
            throw new BaseException("已过期");
        }
        Reservation reservation = new Reservation();
        reservation.setId(id);
        reservation.setStatus(2);
        updateById(reservation);
    }

    @Override
    public void recyclingExpires() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime hourTime = now.withMinute(0).withSecond(0).withNano(0);
        LambdaQueryWrapper<Reservation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.lt(Reservation::getTime,hourTime);
        queryWrapper.eq(Reservation::getStatus,0);
        Reservation reservation = new Reservation();
        reservation.setStatus(3);
        update(reservation,queryWrapper);
    }
}
